package com.moyu.user.service.user.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.moyu.common.core.domain.R;
import com.moyu.common.core.enums.ResultCode;
import com.moyu.common.core.utils.BCryptUtils;
import com.moyu.common.core.utils.BuildAccount;
import com.moyu.common.core.utils.EmailCodeUtils;
import com.moyu.common.redis.service.RedisService;
import com.moyu.user.domain.user.User;
import com.moyu.user.domain.user.dto.UserRegDTO;
import com.moyu.user.mapper.user.UserMapper;
import com.moyu.user.service.user.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 普通用户服务类
 *
 * @Author 赵彦博
 * @Date 2024/12/20 10:39
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private BuildAccount account;

    @Autowired
    private EmailCodeUtils buildEmailCode;

    @Autowired
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String emailAccount;

    @Override
    public User query(String account) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        User user = new User();
        if (account.contains("@")) {
            user = userMapper.selectOne(queryWrapper
                    .select(User::getId, User::getUserAccount, User::getPassword, User::getEmailAddress)
                    .eq(User::getEmailAddress, account));
        } else {
            user = userMapper.selectOne(queryWrapper
                    .select(User::getId, User::getUserAccount, User::getPassword, User::getEmailAddress)
                    .eq(User::getUserAccount, account));
        }
        return user;
    }

    @Override
    public R<User> reg(UserRegDTO userRegDTO) {
        R<User> userR = new R<>();
        // 判断是否数据填写合法
        int res = checkData(userRegDTO);
        // 根据邮箱等信息进行新增用户
        if (res == 0) {
            User user = new User();
            String userAccount = account.init();
            user.setUserAccount(userAccount);
            user.setPassword(BCryptUtils.encryptPassword(userRegDTO.getPassword()));
            user.setEmailAddress(userRegDTO.getEmailAddress());
            user.setNickName(userRegDTO.getNickName());
            user.setState(0);
            try {
                userMapper.insert(user);
                userR.setCode(ResultCode.SUCCESS.getCode());
                userR.setMsg(ResultCode.SUCCESS.getMsg());
                userR.setData(user);
                return userR;
            } catch (Exception e) {
                log.error("执行sql-新增用户出错:" + e.getCause());
            }
        } else {
            userR.setCode(-1);
            userR.setData(null);
            if (res == 1) {
                userR.setMsg("数据不全,请检查是否漏填~");
            } else if (res == 2) {
                userR.setMsg("确认密码和初始密码不一致，请重新输入~");
            } else if (res == 3) {
                userR.setMsg("验证码未填写~");
            } else if (res == 4) {
                userR.setMsg("邮箱填写格式不正确，请重新输入~");
            } else if (res == 5) {
                userR.setMsg("邮箱已被使用,请重新换个邮箱再来注册~");
            } else if (res == 6) {
                userR.setMsg("验证码过期，请重新发送~");
            } else if (res == 7) {
                userR.setMsg("验证码错误，请检查后重新输入~");
            }
        }
        return userR;
    }

    @Override
    public R sendEmailCode(String emailAddress) {
        R r = new R();
        Boolean hasKey = redisService.hasKey(emailAddress);
        if (hasKey == true) {
            return new R(-1, "已经发送过验证码，短时间内不可以重复发送", false);
        }
        String code = buildEmailCode.init();
        Boolean res = sendCode(emailAddress, code);
        if (res) {
            r.setCode(0);
            r.setMsg("验证码发送成功，验证码将于120秒之后过期，请尽快完成注册~");
            r.setData(true);
        } else {
            r.setCode(-1);
            r.setMsg("邮箱信息有误，请检查邮箱的正确性~");
            r.setData(false);
        }
        return r;
    }

    private Boolean sendCode(String emailAddress, String code) {
        SimpleMailMessage msg  = new SimpleMailMessage();
        //标题
        String subject = "【论坛系统】邮箱验证码";
        //正文内容
        String text = "尊敬的用户，您好，您的邮箱验证码为：" + code + ",您当前正在执行邮箱绑定服务，如非本人操作，请忽略此邮件~";
        try {
            //发送邮件的邮箱
            msg.setFrom(emailAccount);
            //发送到哪(邮箱)
            msg.setTo(emailAddress);
            //邮箱标题
            msg.setSubject(subject);
            //邮箱文本
            msg.setText(text);
            mailSender.send(msg);
            redisService.setCacheObject(emailAddress, code, 120l, TimeUnit.SECONDS);
            return true;
        } catch (MailException e) {
            e.getMessage();
            log.error(e.getMessage());
            return false;
        }
    }

    private int checkData(UserRegDTO userRegDTO) {
        String emailAddress = userRegDTO.getEmailAddress();
        String password = userRegDTO.getPassword();
        String passwordRepeat = userRegDTO.getPasswordRepeat();
        String nickName = userRegDTO.getNickName();
        String code = userRegDTO.getCode();
        // 填写数据必填项未填
        if (emailAddress == null || password == null
                || passwordRepeat == null || nickName == null) {
            return 1;
        }
        // 两次密码不一致
        if (!password.equals(passwordRepeat)) {
            return 2;
        }
        // 验证码未填写
        if (code == null) {
            return 3;
        }
        // 邮箱填写格式不正确
        String emailRegex = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$";
        Pattern pattern = Pattern.compile(emailRegex);
        Matcher matcher = pattern.matcher(emailAddress);
        if (matcher.matches() == false) {
            return 4;
        }
        // 邮箱已被使用
        User user = this.query(userRegDTO.getEmailAddress());
        if (user != null) {
            return 5;
        }
        // 验证码过期
        String checkCode  = redisService.getCacheObject(emailAddress, String.class);
        if (checkCode == null) {
            return 6;
        }
        //  验证码不正确
        if (!checkCode.equals(code)) {
            return 7;
        }
        redisService.deleteObject(emailAddress);
        return 0;
    }


}
